#!/usr/bin/env bash

# Utility script to check the game sanity
# As of now, this script does not repair files.
#
# Usage: ./check_integrity.sh FILENAME quick
#    FILENAME : Checksum file e.g. "pkg_version" of the game or voiceover pack
#    "quick"  : Skips md5 checks for more speed but is less reliable

set -e

# ======== Functions

fatal() {
	echo
	for arg in "$@"; do
		echo "  *  $arg" >&2
	done
	echo

	exit 1
}

on_file_mismatch() {
	# 1 = Error Msg, 2 = Filepath
	>&2 echo "$2"
	>&2 echo "    * $1"
}


if [[ $(uname) == "Darwin" || $(uname) == *"BSD" ]]; then
	STATFLAGS="-f %z"
	md5sum() {
		md5 -q $@
	}
else
	STATFLAGS="-c %s"
fi

check_single() {
	# 1 = filepath
	filepath="$1"
	checksum="$2"
	filesize="$3"
	#echo "Testing: $filepath $checksum $filesize"
	if [ ! -e "$filepath" ]; then
		on_file_mismatch "Missing" "$filepath"
		return
	fi

	local size=$(stat $STATFLAGS "$filepath")
	if [ "$size" -ne "$filesize" ]; then
		on_file_mismatch "Size mismatch: $size != $filesize" "$filepath"
		return
	fi

	if [ "$CHECK_MD5" -eq 1 ]; then
		sum=($(md5sum "$filepath"))
		if [ "$sum" != "$checksum" ]; then
			on_file_mismatch "Checksum error: $sum != $checksum" "$filepath"
			return
		fi
	fi
}


# ======== Evaluated variables

MASTER_FILE="$1"
CHECK_MD5=1
JOBS=4

[ ! -e "$MASTER_FILE" ] && fatal \
	"Checksum file $MASTER_FILE not found."

if [ "$2" == "quick" ]; then
	CHECK_MD5=0
	echo "--- Mode: Quick file size checking (fast, less reliable)"
else
	echo "--- Mode: Detailed md5 checking (slow, most reliable)"
fi

echo ""

# This is faster than running "jq" on each line
# outputs a string in form of "Direcotry/File.ext|abc123|10001"
per_line_data=$(jq -r "[.remoteName, .md5, .fileSize] | join(\"|\")" "$MASTER_FILE")

i=0
total=$(echo "$per_line_data" | wc -l)

while IFS='|' read -r filepath checksum filesize; do
	i=$((i + 1))

	while [ $(jobs | wc -l) -gt $JOBS ]; do
		sleep 0.1
	done

	check_single "$filepath" "$checksum" "$filesize" &

	# Log file names every now and then
	if [ $((i % 500)) == 0 ]; then
		percent=$((i * 100 / total))
		echo "--- Progress: ${percent}% (${i} / ${total})"
	fi
done <<< "$per_line_data"

while [ $(jobs | wc -l) -gt 1 ]; do
	sleep 0.1
done

echo ""
echo "==> DONE"

exit 0
